//
//  BenHUDState.swift
//  IdleFish
//
//  Created by Ben on 2021/9/29.
//

import UIKit
import Combine
import SwiftUI

// 声明一个协议，该协议具有显示一般弹窗、显示等待弹窗以及隐藏当前弹窗的功能
protocol BenHUDAble {
    
    func show(message: String, systemImageName: String?)
    
    func wait(message: String?, gifImageName: String)
    
    func hide()
}
// 提供一个默认的实现
extension BenHUDAble {
    func show(message: String, systemImageName: String? = nil) {
        DispatchQueue.main.async {

            BenHUDState.shared.show(message: message, systemImageName: systemImageName)
        }
    }
    
    func wait(message: String?, gifImageName: String) {
        
        
        DispatchQueue.main.async {
            BenHUDState.shared.wait(message: message, gifImageName: gifImageName)
        }
    }
    
    func hide() {
        DispatchQueue.main.async {

            BenHUDState.shared.hide()
        }
    }
}

final class BenHUDState: ObservableObject {
    // 这里实现一个单利的BenHUDState
    static let shared: BenHUDState = BenHUDState()
    
    // 控制网络等待显示与关闭
    @Published var isWait: Bool = false
    
    // 控制消息弹窗显示与关闭
    @Published var isPresented: Bool = false
    
    // 消息内容，网络等待提示语或其他消息
    private(set) var message: String?
    // 使用sf图标需要设置
    private(set) var systemImageName: String?
    // 使用自定义图标需要设置
    private(set) var customImageName: String = ""

    private var cancelable: Set<AnyCancellable> = []
    
    func hide() {
        
        withAnimation {
            isWait = false
            isPresented = false
        }
    }
    
    /// 通过该方法弹出网络等待hud
    /// - Parameters:
    ///   - message: 要显示的等待提示语
    ///   - gifImageName: 要显示的等待gif图片
    func wait(message: String? = nil, gifImageName: String = "hud_wait.gif") {
        self.message = message
        self.customImageName = gifImageName
        
        // 需要显示等待提示的时候，关闭一般消息弹窗
        isPresented = false
        withAnimation {
            isWait = true
        }
    }
    
    /// 通过该方法弹出消息弹窗
    /// - Parameters:
    ///   - message: 要显示的消息
    ///   - systemImageName: 消息中的图标名称，sf
    // 这个时间实际上没有使用，属于UP主之前遗留的小bug
    func show(message: String, systemImageName: String? = nil) {
        
        self.message = message
        self.systemImageName = systemImageName
        
        withAnimation {
            isWait = false
            isPresented = true
        }
    }
    
    
    private var presentedPublisher: AnyPublisher<Bool, Never> {
        $isPresented
            // 每两秒触发一次
            .debounce(for: 2, scheduler: RunLoop.main)
            // 过滤掉前后发出的值相同的通知
            // 连续多次点击，可能会出现模拟器中现在的情况，弹窗无法消失,注释掉过滤相同值通知的方法
//            .removeDuplicates()
            .map { _ in
                return false
            }
            .eraseToAnyPublisher()
    }
    
    init() {
        
        presentedPublisher
            .sink { _isPresented in
                
                withAnimation {
                    self.isPresented = _isPresented
                }
            }
            .store(in: &cancelable)
    }
}
